import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:ichinesereader/controller/cache.dart';
import 'package:ichinesereader/models/class/ClassDetails.dart';
import 'package:ichinesereader/models/class/ClassDetailsDto.dart';
import 'package:ichinesereader/models/class/ClassDetailsNew.dart';
import 'package:ichinesereader/models/class/announcementDto.dart';
import 'package:ichinesereader/models/class/announcementItem.dart';
import 'package:ichinesereader/models/class/announcementsResult.dart';
import 'package:ichinesereader/models/class/classSettingsResult.dart';
import 'package:ichinesereader/models/common/userStatusDto.dart';
import 'package:ichinesereader/models/school/SchoolActivities.dart';
import 'package:ichinesereader/models/school/SchoolAdminProfile.dart';
import 'package:ichinesereader/models/school/SchoolBasicStatics.dart';
import 'package:ichinesereader/models/school/SchoolOverviewData.dart';
import 'package:ichinesereader/models/school/SchoolProgramsResult.dart';
import 'package:ichinesereader/models/school/StudentToClassDto.dart';
import 'package:ichinesereader/models/school/newStudentDto.dart';
import 'package:ichinesereader/models/school/removeClassStudentDto.dart';
import 'package:ichinesereader/models/school/studentNamesList.dart';
import 'package:ichinesereader/models/school/teacherUpdateDto.dart';
import 'package:ichinesereader/models/student/StudentItem.dart';
import 'package:ichinesereader/models/school/SchoolStudents.dart';
import 'package:ichinesereader/models/school/teacherItem.dart';
import 'package:ichinesereader/models/teacher/TeacherClass.dart';
import 'package:ichinesereader/service/schooladmin.dart';
import 'package:ichinesereader/models/common/StatusMessageResult.dart';
import 'package:ichinesereader/service/user.dart';
import '../models/school/SchoolAdminProfileUpdateDto.dart';
import '../models/school/moveClassStudentsDto.dart';
import '../models/school/teacherCreateDto.dart';
import 'package:ichinesereader/utils/log.dart';

class SchoolAdminController extends GetxController with StateMixin<dynamic> {
  SchoolAdminServiceProvider _schoolServiceProvider =
      new SchoolAdminServiceProvider();
  UserServiceProvider _userServiceProvider = new UserServiceProvider();
  var box = Hive.box('appconfig');

  Rx<StatusMessageResult> _statusMessageResult =
      Rx<StatusMessageResult>(StatusMessageResult());
  Rx<StatusMessageResult> get statusMessageResult => this._statusMessageResult;

  StatusMessageResult _statusResult = new StatusMessageResult();
  List<SchoolProgram> _schoolPrograms = <SchoolProgram>[].obs;
  List<StudentItem> _studentItems = <StudentItem>[].obs;
  List<StudentItem> _studentItemsSelected = <StudentItem>[].obs;
  List<StudentItem> _studentItemsNotInClass = <StudentItem>[].obs;
  List<StudentItem> _studentItemsNotInClassOriginal = <StudentItem>[].obs;
  List<AnnouncementItem> _announcementItems = <AnnouncementItem>[].obs;
  List<Announcement> _studentannouncements = <Announcement>[].obs;
  List<ClassDetails> _classItems = <ClassDetails>[].obs;
  List<ClassDetails> _classItemsWithoutAll = <ClassDetails>[].obs;
  Rx<ClassDetails> _classDetails = Rx<ClassDetails>(ClassDetails());
  Rx<ClassDetails> _currentSchoolAdminClass = Rx<ClassDetails>(ClassDetails());
  Rx<ClassDetailsNew> _classDetailsNew = Rx<ClassDetailsNew>(ClassDetailsNew());
  Rx<Program> _currentClassPrograms = Rx<Program>(Program());
  Rx<ClassDetails> _currentSchoolAdminClassWithAll =
      Rx<ClassDetails>(ClassDetails());
  List<TeacherClass> _teacherClasses = <TeacherClass>[].obs;
  List<TeacherItem> _teacherItems = <TeacherItem>[].obs;

  Rx<SchoolAdminProfile> _schoolAdminProfile =
      Rx<SchoolAdminProfile>(SchoolAdminProfile());

  Rx<SchoolOverviewData> _schoolOverviewData =
      Rx<SchoolOverviewData>(SchoolOverviewData());
  Rx<SchoolBasicStatics> _schoolBasicStatics =
      Rx<SchoolBasicStatics>(SchoolBasicStatics());
  Rx<SchoolActivities> _schoolActivities =
      Rx<SchoolActivities>(SchoolActivities());
  RxString _selectedSubThemeProgramId = ''.obs;
  Rx<bool> shareAll = Rx<bool>(false.obs.value);

  RxString get selectedSubThemeProgramId => this._selectedSubThemeProgramId;
  Rx<Program> get currentClassPrograms => this._currentClassPrograms;
  List<SchoolProgram> get schoolPrograms => this._schoolPrograms;
  List<StudentItem> get studentItems => this._studentItems;
  List<StudentItem> get studentItemsSelected => this._studentItemsSelected;
  List<StudentItem> get studentItemsNotInClass => this._studentItemsNotInClass;
  List<StudentItem> get studentItemsNotInClassOriginal =>
      this._studentItemsNotInClassOriginal;
  List<ClassDetails> get classItems => this._classItems;
  List<ClassDetails> get classItemsWithoutAll => this._classItemsWithoutAll;
  Rx<ClassDetails> get classDetails => this._classDetails;
  Rx<ClassDetailsNew> get classDetailsNew => this._classDetailsNew;
  ClassDetails get currentSchoolAdminClass =>
      this._currentSchoolAdminClass.value;
  Rx<ClassDetails> get currentSchoolAdminClassWithoutAll =>
      this._currentSchoolAdminClassWithAll;
  List<TeacherClass> get teacherClasses => this._teacherClasses;
  List<TeacherItem> get teacherItems => this._teacherItems;

  Rx<SchoolAdminProfile> get schoolAdminProfile => this._schoolAdminProfile;
  List<AnnouncementItem> get announcementItems => this._announcementItems;
  List<Announcement> get studentannouncements => this._studentannouncements;
  Rx<SchoolOverviewData> get schoolOverviewData => this._schoolOverviewData;
  Rx<SchoolBasicStatics> get schoolBasicStatics => this._schoolBasicStatics;
  Rx<SchoolActivities> get schoolActivities => this._schoolActivities;
  Rx<bool> get getShareAll => this.shareAll;

  // List<BasketItem> get basketItems => this._basketItems;
  // Rx<String> get recordingLocation => this._recordingLocation;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  dispose() {
    super.dispose();
  }

  void setSubThemeProgramId(String subProgramId) {
    this._selectedSubThemeProgramId.value = subProgramId;
  }

  void setSchoolAdminCurrentClass(ClassDetails tc) async {
    this._currentSchoolAdminClass.value = tc;
    box.put(CacheManagerKey['currentclass'].toString(), tc.classId);
    change(this._currentSchoolAdminClass, status: RxStatus.success());
  }

  void setSchoolAdminCurrentClassWithoutAll(ClassDetails tc) async {
    this._currentSchoolAdminClassWithAll.value = tc;
    box.put(CacheManagerKey['currentclass'].toString(), tc.classId);
    change(this._currentSchoolAdminClassWithAll, status: RxStatus.success());
  }

  void clearStudentSelectedList() {
    this._studentItemsSelected.clear();
  }

  void addStudentToSelectedList(List<StudentItem> students) {
    this._studentItemsSelected.clear();
    this._studentItemsSelected.assignAll(students);
    // if (this._studentItemsSelected.isNotEmpty) {
    //   var item = this
    //       ._studentItemsSelected
    //       .where((element) => element.id == student.id)
    //       .first;
    //   if (item.userName != null) this._studentItemsSelected.add(student);
    // } else {
    //   this._studentItemsSelected.add(student);
    // }
    // change(this._studentItemsSelected, status: RxStatus.success());
  }

  void removeStudentFromSelectedList(StudentItem student) {
    if (this._studentItemsSelected.isNotEmpty) {
      this
          ._studentItemsSelected
          .removeWhere((element) => element.id == student.id);
      change(this._studentItemsSelected, status: RxStatus.success());
    }
  }

  ClassDetails getCurrentClass() {
    return this._currentSchoolAdminClass.value;
  }

  void addStudentToStudentItems(StudentItem student) {
    this._studentItems.insert(0, student);
    change(this._studentItems, status: RxStatus.success());
  }

  void changeCheckedValue(bool value) {
    this.shareAll.value = value;
    change(this.shareAll, status: RxStatus.success());
  }

  void removeStudentFromStudentItems(StudentItem student) {
    this._studentItems.removeWhere((element) => element.id == student.id);
    change(this._studentItems, status: RxStatus.success());
  }

  void updateStudentItem(StudentItem item) async {
    if (this._studentItems.isNotEmpty) {
      var student =
          this._studentItems.where((element) => element.id == item.id);
      this._studentItems.remove(student);
      this._studentItems.insert(0, item);
      change(this._studentItems, status: RxStatus.success());
    }
  }

  void createClasss(ClassDetailsDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      var response = await _schoolServiceProvider.createClass(dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);

        _statusResult.status = 1000;
        _statusResult.message = data.message;
        //change(_statusResult, status: RxStatus.success());
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
        //change(_statusResult, status: RxStatus.error('Failed due to error'));
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      //change(_statusResult, status: RxStatus.error());
      Log.debug(error);
    }
  }

  Future<StatusMessageResult> updateClasss(ClassDetailsDto dto) async {
    var _statusResult = new StatusMessageResult();
    EasyLoading.show();
    try {
      var response = await _schoolServiceProvider.updateClass(dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> removeClasss(String classId) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _schoolServiceProvider.removeClass(classId);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        if (this._classItems.isNotEmpty) {
          this._classItems.removeWhere((element) => element.classId == classId);
          change(this._classItems, status: RxStatus.success());
        }
        if (this._classItemsWithoutAll.isNotEmpty) {
          this
              ._classItemsWithoutAll
              .removeWhere((element) => element.classId == classId);
          change(this._classItemsWithoutAll, status: RxStatus.success());
        }
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void fetchSchoolAllClassesDetailsWithoutAll() async {
    try {
      var response = await _schoolServiceProvider.getSchoolAllClassesDetails();
      if (response.statusCode == 200) {
        var data = classDetailsFromJson(response.bodyString);
        if (data.isNotEmpty) {
          data.sort((a, b) {
            int end1 = a.createDate!.toInt();
            int end2 = b.createDate!.toInt();
            return end2.compareTo(end1);
          });
          _classItemsWithoutAll.assignAll(data);
          this._classItems = data;
          ClassDetails cd = new ClassDetails();
          cd.classId = 'All';
          cd.className = 'All';
          this._classItems.insert(0, cd);
          this._currentSchoolAdminClass.value = this._classItems[0];
          change(_classItemsWithoutAll, status: RxStatus.success());
          change(_classItems, status: RxStatus.success());
        } else {
          change(_classItemsWithoutAll, status: RxStatus.empty());
          ClassDetails cd = new ClassDetails();
          cd.classId = 'All';
          cd.className = 'All';
          this._classItems.assign(cd);
          this._currentSchoolAdminClass.value = this._classItems[0];
          change(_classItems, status: RxStatus.success());
        }
        box.put(CacheManagerKey['currentclass'].toString(),
            this._currentSchoolAdminClass.value.classId);
        change(this._currentSchoolAdminClass, status: RxStatus.success());
      } else {
        change(null, status: RxStatus.error());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    }
  }

  void resetClassDetailsNew() {
    //this._classDetailsNew.value.classId = null;
    this._classDetailsNew.value = new ClassDetailsNew();
  }

  void fetchSchoolPrograms() async {
    try {
      var response = await _schoolServiceProvider.getSchoolPrograms();
      if (response.statusCode == 200) {
        var data = schoolProgramsResultFromJson(response.bodyString);
        if (data.result != null && data.result?.subResult != null) {
          data.result?.subResult?.forEach(
            (element) => _schoolPrograms.add(element),
          );
          change(_schoolPrograms, status: RxStatus.success());
        } else {
          change(null, status: RxStatus.empty());
        }
      } else {
        change(null, status: RxStatus.empty());
      }
    } catch (error) {
      change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      Log.debug(error);
    }
  }

  void fetchClassAnnouncementsByClassId(String classId) async {
    try {
      EasyLoading.show();
      var response =
          await _schoolServiceProvider.getClassAnnouncementsByClassId(classId);
      if (response.statusCode == 200) {
        var data = classAnnouncementsResultFromJson(response.bodyString);
        if (data.list != null) {
          this._announcementItems.clear();

          data.list?.forEach((announcement) {
            AnnouncementItem item = new AnnouncementItem();
            item.announcementType = announcement.announcementType;
            item.id = announcement.id;
            item.message = announcement.message;
            item.point = announcement.point;
            item.when = announcement.when;

            if (announcement.allStudentsClass == true) {
              item.students = 'All class students';
            } else {
              String names = '';
              announcement.students?.forEach((student) {
                names = names + '${student.userName}' + ';';
              });
              item.students = names.trim();
            }
            this._announcementItems.add(item);
          });
          if (_announcementItems.length > 0)
            change(this._announcementItems, status: RxStatus.success());
          else
            change(null, status: RxStatus.empty());
        }
      } else {
        change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      }
    } catch (error) {
      change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<StatusMessageResult> sendClassAnnouncementsByClassId(
      String classId, ClassAnnouncementDto dto) async {
    try {
      _statusResult = new StatusMessageResult();
      EasyLoading.show();
      var response =
          await _schoolServiceProvider.sendClassAnnouncement(classId, dto);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Success';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed to send message.';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void fetchStudentClassAnnouncementsByClassId(String classId) async {
    try {
      //change(null, status: RxStatus.loading());
      EasyLoading.show();
      var response = await _schoolServiceProvider
          .getStudentClassAnnouncementsByClassId(classId);
      if (response.statusCode == 200) {
        var data = announcementFromJson(response.bodyString);
        if (data.isNotEmpty) {
          this._studentannouncements.clear();
          this._studentannouncements.assignAll(data);
          if (_studentannouncements.length > 0)
            change(this._studentannouncements, status: RxStatus.success());
          else
            change(null, status: RxStatus.empty());
        }
        // {
        //   change(this._studentannouncements, status: RxStatus.empty());
        // }
      } else {
        change(this._studentannouncements, status: RxStatus.empty());
        //change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      }
    } catch (error) {
      change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  void createLoginCardsByClassId(String classId) async {
    try {
      _statusResult = new StatusMessageResult();
      var response =
          await _schoolServiceProvider.createClassLoginCards(classId);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Success';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    }
    _statusMessageResult.value = _statusResult;
  }

// 新版获取学生的接口，老版数据似乎不太正常
  void fetchSchoolStudentsByClassId(String classId, bool onlyEnabled) async {
    try {
      this._studentItemsSelected.clear();
      EasyLoading.show();
      //change(_studentItems, status: RxStatus.loading());
      var response = await _schoolServiceProvider
          .getSchoolClassesDetailsNewByClassId(classId);
      if (response.statusCode == 200) {
        var data = classDetailsNewFromJson(response.bodyString);
        if (data.studentResps!.length > 0) {
          data.studentResps?.forEach((student) {
            student.classNames = data.className;
          });
          if (onlyEnabled) {
            data.studentResps
                ?.removeWhere((element) => element.disabled == true);
          }
          _studentItems.assignAll(data.studentResps as List<StudentItem>);
          change(_studentItems, status: RxStatus.success());
        } else {
          _studentItems.clear();
          change(_studentItems, status: RxStatus.success());
          //change(null, status: RxStatus.empty());
        }
      }
    } catch (error) {
      Log.debug(error);
      change(null, status: RxStatus.error());
    } finally {
      EasyLoading.dismiss();
    }
  }

//新版带program 的接口
  void fetchClassDetailsNewByClassId(String classId) async {
    try {
      //change(_classDetailsNew, status: RxStatus.loading());
      EasyLoading.show();
      var response = await _schoolServiceProvider
          .getSchoolClassesDetailsNewByClassId(classId);
      if (response.statusCode == 200) {
        var data = classDetailsNewFromJson(response.bodyString);

        box.put(CacheManagerKey['currentclassdetails'].toString(),
            response.bodyString);

        this._classDetailsNew.value = data;
        this._currentClassPrograms.value = data.program as Program;

        if (data.studentResps != null && data.studentResps!.length > 0) {
          this._studentItems.assignAll(data.studentResps as List<StudentItem>);
        }
        box.put(CacheManagerKey['currentclassProgramId'].toString(),
            this._currentClassPrograms.value.id);
        if (data.program != null) {
          Tree programTree = data.program!.tree!.lowerProgram!
              .where((element) =>
                  element.id == this.currentClassPrograms.value.id.toString())
              .first;
          if (programTree.lowerProgram != null &&
              programTree.lowerProgram!.length > 0)
            this._selectedSubThemeProgramId.value =
                programTree.lowerProgram![0].id.toString();
          else
            this._selectedSubThemeProgramId.value = '';
        }
        change(_classDetailsNew, status: RxStatus.success());
      } else {
        change(_classDetailsNew, status: RxStatus.empty());
      }
    } catch (error) {
      change(null, status: RxStatus.error('Oops, something wrong ...'.tr));
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  //新版class settings 的接口
  Future<ClassSettingsResult> getClassSettingsByClassId(String classId) async {
    var data = ClassSettingsResult();
    try {
      var response =
          await _schoolServiceProvider.getClassSettingsByClassId(classId);
      if (response.statusCode == 200) {
        data = classSettingsResultFromJson(response.bodyString);
      }
    } catch (error) {
      Log.debug(error);
    }
    return data;
  }

  void fetchSchoolAllStudents(int page, int limit) async {
    try {
      EasyLoading.show();
      //change(_studentItems, status: RxStatus.loading());
      var response =
          await _schoolServiceProvider.getSchoolStudents(page, limit);
      if (response.statusCode == 200) {
        var totalStudentList = <StudentItem>[];
        var data = schoolStudentsFromJson(response.bodyString);
        totalStudentList.addAll(data.list as List<StudentItem>);
        if (data.total! > limit) {
          int totalPage = ((data.total! + limit - 1) ~/ limit).toInt();
          for (int t = 1; t < totalPage; t++) {
            response = await _schoolServiceProvider.getSchoolStudents(t, limit);
            data = schoolStudentsFromJson(response.bodyString);
            totalStudentList.addAll(data.list as List<StudentItem>);
          }
        }
        _studentItems.assignAll(totalStudentList);
        if (_studentItems.isNotEmpty) {
          change(_studentItems, status: RxStatus.success());
        } else {
          change(_studentItems, status: RxStatus.empty());
        }
      } else {
        change(_studentItems, status: RxStatus.empty());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  void searchSchoolStudents(String query) async {
    try {
      change(_studentItems, status: RxStatus.loading());
      var response = await _schoolServiceProvider.searchSchoolStudents(query);
      if (response.statusCode == 200) {
        _studentItems.clear();
        var data = schoolStudentsFromJson(response.bodyString);
        _studentItems.assignAll(data.list as List<StudentItem>);
        if (_studentItems.isNotEmpty) {
          change(_studentItems, status: RxStatus.success());
        } else {
          change(_studentItems, status: RxStatus.empty());
        }
      } else {
        change(null, status: RxStatus.error());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    }
  }

  void fetchAllStudentsNotInGivenClass(String classId) async {
    try {
      //change(_studentItemsNotInClass, status: RxStatus.loading());
      EasyLoading.show();
      var response =
          await _schoolServiceProvider.getAllStudentsNotInGivenClass(classId);
      if (response.statusCode == 200) {
        _studentItemsNotInClass.clear();
        var data = studentItemsFromJson(response.bodyString);
        _studentItemsNotInClass.assignAll(data);
        _studentItemsNotInClassOriginal.assignAll(data);
        change(_studentItemsNotInClass, status: RxStatus.success());
      } else {
        change(_studentItemsNotInClass, status: RxStatus.empty());
      }
    } catch (error) {
      change(_studentItemsNotInClass, status: RxStatus.error());
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  void searchStudentsNotInGivenClass(String query) async {
    try {
      if (_studentItemsNotInClassOriginal.isNotEmpty) {
        _studentItemsNotInClass.clear();
        var searchedStudents = _studentItemsNotInClassOriginal
            .where((element) =>
                element.firstName!.contains('$query') ||
                element.lastName!.contains('$query') ||
                element.userName!.contains('$query'))
            .toList();
        if (searchedStudents.isNotEmpty) {
          _studentItemsNotInClass.assignAll(searchedStudents);
          change(this._studentItemsNotInClass, status: RxStatus.success());
        } else {
          change(this._studentItemsNotInClass, status: RxStatus.empty());
        }
      } else {
        change(null, status: RxStatus.empty());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    }
  }

  void resumeStudentsNotInGivenClass() async {
    try {
      if (_studentItemsNotInClassOriginal.isNotEmpty) {
        this
            ._studentItemsNotInClass
            .assignAll(this._studentItemsNotInClassOriginal);
        change(this._studentItemsNotInClass, status: RxStatus.success());
      } else {
        change(this._studentItemsNotInClass, status: RxStatus.empty());
      }
    } catch (error) {
      Log.debug(error);
    }
  }

  // void _addStudentsToClass(String classId, String userName) async {
  //   StudentToClassDto data = new StudentToClassDto();
  //   data.classId = classId;
  //   data.studentsUserName = [userName.toString()];
  //   await _schoolServiceProvider.addStudentsToClass(data);
  // }

  Future<StatusMessageResult> createStudent(
      String classId, StudentDetailsDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      var response = await _userServiceProvider.createStudent(dto);
      // _addStudentsToClass(
      //     currentSchoolAdminClass.classId.toString(), dto.userName.toString());
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        //////{"status":1000,"message":"Congratulations, your account has been created successfully. ","result":null}
        /// create student/ class成功之后在result返回唯一的识别id，这样就能省去再去调用一次而刷新界面
        if (classId != '' && classId != 'All') {
          StudentToClassDto studentDto = new StudentToClassDto();
          studentDto.classId = classId;
          studentDto.studentsUserName = [];
          studentDto.studentsUserName?.add(dto.userName.toString());
          addCreatedStudentsToClass(studentDto);
        }
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    }
    return _statusResult;
  }

  Future<StatusMessageResult> updateStudent(StudentDetailsDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.updateStudent(dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed to update student!';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> updateStudentsStatus(UserStatusDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.updateStudentStatus(dto);
      if (response.statusCode == 200) {
        //var data = propertyMessageFromJson(response.bodyString);
        if (response.bodyString == '[]') {
          dto.userNames?.forEach((username) {
            var student = this
                ._studentItems
                .where((element) => element.userName == username)
                .first;
            if (student.id != null)
              student.disabled = dto.enable as bool ? false : true;
          });
          change(this._studentItems, status: RxStatus.success());
        }
      }
    } catch (error) {
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void updateStudentIncentive(String username, bool disabled) async {
    //change(this._studentItems, status: RxStatus.loading());
    try {
      var response = await _schoolServiceProvider.updateStudentIncentive(
          username, disabled);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Successful';
        var student = this
            ._studentItems
            .where((element) => element.userName == username)
            .first;
        if (student.userName != null)
          student.gameDisable = disabled ? true : false;
        change(this._studentItems, status: RxStatus.success());
      }
    } catch (error) {
      Log.debug(error);
    }
  }

  void updateClassIncentive(String classId, bool disabled) async {
    try {
      EasyLoading.show();
      var response =
          await _schoolServiceProvider.updateClassIncentive(classId, disabled);
      if (response.statusCode == 200) {
        if (this._studentItems.isNotEmpty) {
          this._studentItems.forEach((student) {
            student.gameDisable = disabled ? true : false;
          });
        }
        change(this._studentItems, status: RxStatus.success());
      }
    } catch (error) {
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<StatusMessageResult> deleteStudents(StudentNamesList data) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.deleteStudents(data);
      if (response.statusCode == 200) {
        if (data.studentsName!.isNotEmpty) {
          data.studentsName?.forEach((username) {
            this
                ._studentItems
                .removeWhere((element) => element.userName == username);
          });
        }
        change(this._studentItems, status: RxStatus.success());
        _statusResult.status = 1000;
        _statusResult.message = 'Deleted';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed to delete student';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> removeStudentsFromClass(
      String classId, RemoveClassStudentDto data) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response =
          await _schoolServiceProvider.removeStudentsFromClass(classId, data);
      if (response.statusCode == 200) {
        if (data.students!.isNotEmpty) {
          data.students?.forEach((username) {
            this
                ._studentItems
                .removeWhere((element) => element.userName == username);
          });
        }
        change(this._studentItems, status: RxStatus.success());
        _statusResult.status = 1000;
        _statusResult.message = 'Removed';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void addCreatedStudentsToClass(StudentToClassDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      var response = await _schoolServiceProvider.addStudentsToClass(dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    }
    _statusMessageResult.value = _statusResult;
  }

  Future<StatusMessageResult> addStudentsToClass(StudentToClassDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _schoolServiceProvider.addStudentsToClass(dto);
      if (response.statusCode == 200) {
        fetchSchoolStudentsByClassId(dto.classId.toString(), false);
        dto.studentsUserName?.forEach((username) {
          var student = this
              ._studentItemsNotInClass
              .where((element) => element.userName == username)
              .first;
          if (student.userName != null) {
            this
                ._studentItemsNotInClass
                .removeWhere((element) => element.userName == student.userName);
          }
        });
        change(this._studentItemsNotInClass, status: RxStatus.success());
        this
            ._studentItemsNotInClassOriginal
            .assignAll(this._studentItemsNotInClass);
        _statusResult.status = 1000;
      } else {
        _statusResult.status = 0;
      }
    } catch (error) {
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void fetchSchoolTeachers() async {
    try {
      EasyLoading.show();
      var response = await _schoolServiceProvider.getAllTeachersForASchool();
      if (response.statusCode == 200) {
        var data = teacherItemsFromJson(response.bodyString);
        if (data.isNotEmpty) {
          _teacherItems.assignAll(data);
          change(this._teacherItems, status: RxStatus.success());
        } else {
          change(this._teacherItems, status: RxStatus.empty());
        }
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<StatusMessageResult> createTeacher(TeacherCreateDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.createTeacher(dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);
        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> updateTeacherDetails(
      String userName, TeacherUpdateDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response =
          await _userServiceProvider.updateTeacherDetails(userName, dto);
      if (response.statusCode == 200) {
        var data = statusMessageResultFromJson(response.bodyString);

        _statusResult.status = 1000;
        _statusResult.message = data.message;
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> updateTeachersStatus(UserStatusDto dto) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.updateTeacherStatus(dto);
      if (response.statusCode == 200) {
        //var data = propertyMessageFromJson(response.bodyString);
        if (response.bodyString == '') {
          // dto.userNames?.forEach((username) {
          //   var item = this
          //       ._teacherItems
          //       .where((element) => element.userName == username)
          //       .first;
          //   if (item.userName != null)
          //     item.disabled = dto.enable == true ? false : true;
          // });
          // change(this._teacherItems, status: RxStatus.success());
          _statusResult.status = 1000;
          _statusResult.message = 'Successful';
        } else {
          //change(this._teacherItems, status: RxStatus.success());
          _statusResult.status = 0;
          _statusResult.message = 'Failed';
        }
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> removeTeacher(String userName) async {
    _statusResult = new StatusMessageResult();
    try {
      EasyLoading.show();
      var response = await _userServiceProvider.removeTeacher(userName);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Success';
        if (this._teacherItems.isNotEmpty)
          this
              ._teacherItems
              .removeWhere((element) => element.userName == userName);
        change(this._teacherItems, status: RxStatus.success());
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  void fetchSchoolAdminProfile() async {
    try {
      EasyLoading.show();
      //change(this._schoolAdminProfile, status: RxStatus.loading());
      var response = await _schoolServiceProvider.getSchoolAdminProfile();
      if (response.statusCode == 200) {
        var data = schoolAdminProfileFromJson(response.bodyString);
        this._schoolAdminProfile.value = data;
        change(this._schoolAdminProfile, status: RxStatus.success());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<StatusMessageResult> updateSchoolAdminProfile(
      SchoolAdminProfileUpdateDto profileDto,
      bool disableClassLeaderBoard,
      bool disableWorldClassLeaderBoard) async {
    _statusResult = StatusMessageResult();
    try {
      EasyLoading.show();
      await _schoolServiceProvider
          .disableClassLeaderBoard(disableClassLeaderBoard);
      await _schoolServiceProvider
          .disableWorldClassLeaderBoard(disableWorldClassLeaderBoard);
      var response =
          await _schoolServiceProvider.updateSchoolAdminProfile(profileDto);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Success';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

  Future<StatusMessageResult> moveClassStudents(
      MoveClassStudentsDto data) async {
    try {
      EasyLoading.show();
      var response = await _schoolServiceProvider.moveClassStudents(data);
      if (response.statusCode == 200) {
        _statusResult.status = 1000;
        _statusResult.message = 'Success';
      } else {
        _statusResult.status = response.statusCode;
        _statusResult.message = 'Failed to move students, please try later.';
      }
    } catch (error) {
      _statusResult.status = 0;
      _statusResult.message = 'Oops, something wrong ...'.tr;
      Log.debug(error);
    } finally {
      EasyLoading.dismiss();
    }
    return _statusResult;
  }

////show in school admin home, keep it here
  void fetchSchoolOverviewData() async {
    try {
      var response = await _schoolServiceProvider.getSchoolOverviewData();
      if (response.statusCode == 200) {
        var data = schoolOverviewDataFromJson(response.bodyString);
        this._schoolOverviewData.value = data;
        change(this._schoolOverviewData, status: RxStatus.success());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    }
  }

////show in school admin home, keep it here
  void fetchSchoolBasicStatics() async {
    try {
      var response = await _schoolServiceProvider.getSchoolBasicStatics();
      if (response.statusCode == 200) {
        var data = schoolBasicStaticsFromJson(response.bodyString);
        this._schoolBasicStatics.value = data;
        change(this._schoolBasicStatics, status: RxStatus.success());
      }
    } catch (error) {
      change(null, status: RxStatus.error());
      Log.debug(error);
    }
  }

////show in school admin home, keep it here
  void fetchSchoolActivities() async {
    try {
      var response = await _schoolServiceProvider.getSchoolActivities();
      if (response.statusCode == 200) {
        var data = schoolActivitiesFromJson(response.bodyString);
        this._schoolActivities.value = data;
        change(this._schoolActivities, status: RxStatus.success());
      }
    } catch (error) {
      change(this._schoolActivities, status: RxStatus.error());
      Log.debug(error);
    }
  }
}
